use super::{err, err_value, get_dir, json, throw_err, ECode, RNull, SvCache, Value};
use std::fs;
use std::path::Path;
use tracing::{instrument, warn};

#[instrument(skip_all, name = "list_mod")]
pub fn list_mod(md: &str) -> Option<Vec<String>> {
    let path = format!("{}/{}", get_dir(), md);
    let dir = Path::new(&path);

    if !dir.is_dir() {
        return None;
    }

    let dir = match fs::read_dir(dir) {
        Ok(v) => v,
        Err(e) => {
            warn!(target: "文件目录错误", "dir error: {:?}", e);
            return None;
        }
    };

    let mut ret = Vec::new();

    for entry in dir {
        let entry = match entry {
            Ok(v) => v,
            Err(e) => {
                warn!(target: "文件错误", "entry error: {:?}", e);
                return None;
            }
        };

        let p = entry.path();

        let file = match p.as_path().file_name() {
            Some(v) => v,
            None => continue,
        };

        if let Some(f) = file.to_str() {
            if f.starts_with(".") {
                continue;
            }

            ret.push(f.to_string());
        }
    }

    Some(ret)
}

pub async fn scan_mod(k: &str, cache: &SvCache) -> Result<(), Value> {
    match list_mod(k) {
        Some(it) => {
            cache.insert(k.to_string(), json!(it)).await;
        }
        None => {
            cache.invalidate(k).await;
        }
    }

    Ok(())
}

pub fn rm_file(f: &str) -> RNull {
    let path = Path::new(f);

    if path.is_dir() {
        return Ok(());
    }

    if let Err(e) = fs::remove_file(path) {
        throw_err!(ECode::FileDel, e);
    }

    Ok(())
}
